package com.ypan.monitor.osutils;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.regex.Pattern;

import com.ypan.monitor.R;

import android.content.Context;
import android.os.Build;

public class Cpu {
	private static Cpu instance = null;
	private static Context mContext = null;
	//
	public String cpuStr = " "; // CPU名称
	// CPU占用率 及最大和最小使用率
	public CPULoad cpuLoad = null;
	public int nbCores = 1; // CPU个数
	public int[] coreFreq = null;
	public int maxClockFreq = -1;
	public int minClockFreq = -1;
	// /proc/cpuinfo中对应的参数说明
	public int implementerID = -1; // CPU implementer
	public int architecture = -1; // CPU architecture
	public int part = -1; // CPU part
	public int revision = -1;
	public int variant = -1;
	public int process = -1; // nm级别 ,由上面的型号推算出来的
	// Processor
	public String processor = " ";
	// Feature
	public String features = " ";

	private Cpu() {

	}

	public static Cpu getInstance(Context ctx) {
		synchronized (Cpu.class) {
			if (instance == null) {
				instance = new Cpu();
				mContext = ctx;
			}
			return instance;
		}
	}

	// 初始化数据
	public void init() {
		nbCores = getCpuNums();
		coreFreq = new int[nbCores];
		cpuLoad = new CPULoad();
		try {
			getCpuInfos();
		} catch (Exception e) {
			e.printStackTrace();
		}
		refresh();
	}

	// 刷新CPU的使用率
	public void refresh() {
		if (cpuLoad != null) {
			cpuLoad.refreshUsage();
		}
		for (int i = 0; i < nbCores; i++) {
			coreFreq[i] = getCPUCurFreq(i);
		}
	}

	// 获取CPU的个数
	private int getCpuNums() {
		try {
			int i = new File("/sys/devices/system/cpu")
					.listFiles(new FileFilter() {

						@Override
						public boolean accept(File pathname) {
							return Pattern.matches("cpu[0-9]",
									pathname.getName());
						}
					}).length;
			return i;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return 1;
	}

	// 获取CPU当前运行频率
	private int getCPUCurFreq(int num) {
		int curFreq = 0;
		try {
			curFreq = SystemUtils
					.readSystemFileAsInt("/sys/devices/system/cpu/cpu" + num
							+ "/cpufreq/scaling_cur_freq");
		} catch (Exception e) {
		}
		return curFreq;
	}

	// 获取CPU最大可运行频率
	private int getCPUMaxFreq() {
		int curFreq = 0;
		try {
			curFreq = SystemUtils
					.readSystemFileAsInt("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return curFreq;
	}

	// 获取CPU最小可运行频率
	private int getCPUMinFreq() {
		int curFreq = 0;
		try {
			curFreq = SystemUtils
					.readSystemFileAsInt("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return curFreq;
	}

	private boolean getCpuInfos() {
		String str = Build.CPU_ABI;
		maxClockFreq = getCPUMaxFreq();
		minClockFreq = getCPUMinFreq();
		if (str.contains("armeabi"))
			return getCPUinfos_arm();
		if (str.contains("x86"))
			return getCPUinfos_x86();
		return true;
	}

	private boolean getCPUinfos_arm() {
		Scanner scanner = null;
		try {
			scanner = new Scanner(new FileInputStream("/proc/cpuinfo"));
			while (scanner.hasNextLine()) {
				if (scanner.findInLine("CPU implementer\t:") != null) {
					implementerID = Integer.decode(scanner.nextLine().trim())
							.intValue();
				} else if (scanner.findInLine("CPU variant\t:") != null) {
					variant = Integer.decode(scanner.nextLine().trim())
							.intValue();
				} else if (scanner.findInLine("CPU architecture\t:") != null) {
					architecture = Integer.decode(scanner.nextLine().trim())
							.intValue();
				} else if (scanner.findInLine("CPU part\t:") != null) {
					part = Integer.decode(scanner.nextLine().trim()).intValue();
				} else if (scanner.findInLine("CPU revision\t:") != null) {
					revision = Integer.decode(scanner.nextLine().trim())
							.intValue();
				} else if (scanner.findInLine("Hardware\t:") != null) {
					cpuStr = scanner.nextLine().trim();
				} else if (scanner.findInLine("Processor\t:") != null) {
					processor = scanner.nextLine().trim();
				} else if (scanner.findInLine("Features\t:") != null) {
					features = scanner.nextLine().trim();
				} else {
					scanner.nextLine();
				}
			}

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			scanner.close();
		}
		return true;
	}

	private boolean getCPUinfos_x86() {
		Scanner scanner = null;
		try {
			scanner = new Scanner(new FileInputStream("/proc/cpuinfo"));
			while (scanner.hasNextLine()) {
				if (scanner.findInLine("model name\t:") != null) {
					cpuStr = scanner.nextLine();
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			scanner.close();
		}

		return true;
	}

	public ArrayList<ListItem> getItems() {
		ArrayList<ListItem> list = new ArrayList<ListItem>();
		list.add(new ListItem(mContext.getString(R.string.cpu), cpuStr));
		list.add(new ListItem(mContext.getString(R.string.processor), processor));
		list.add(new ListItem(mContext.getString(R.string.features), features));
		list.add(new ListItem(mContext.getString(R.string.cores), "" + nbCores));
		list.add(new ListItem(mContext.getString(R.string.clock), getClockStr(minClockFreq) + "-"
				+ getClockStr(maxClockFreq)));
		for (int i = 0; i < nbCores; i++) {
			list.add(new ListItem(mContext.getString(R.string.core)+" " + i, getClockStr(coreFreq[i])));
		}
		list.add(new ListItem(mContext.getString(R.string.usage), cpuLoad.getUsage() + "%"));
		return list;
	}

	private String getClockStr(int clock) {
		if (clock > 1000 * 1000) {
			return Double.toString((float) clock / 1000.00D / 1000.00D) + "GHz";
		} else if (clock > 1000) {
			return Double.toString((float) clock / 1000.00D) + "MHz";
		} else if (clock > 1) {
			return Double.toString(clock) + "KHz";
		} else {
			return mContext.getString(R.string.stopped);
		}
	}
}
